package sliceTest

import (
	"errors"
	"fmt"
	"reflect"
)

func RemoveElemFromSlice(arg int) {
	a := []int{1, 2, 3, 4, 5, 6}
	for k, v := range a {
		if v == arg {
			a = append(a[0:k], a[k+1:]...)
		}
	}
}

type mySlice struct {
	v     reflect.Value
	count int
}

func NewMySlice(t reflect.Type, cap int) *mySlice {
	if cap <= 0 {
		cap = 64
	}
	return &mySlice{reflect.MakeSlice(reflect.SliceOf(t), 0, cap), 0}
}

func (m *mySlice) Put(val interface{}) (err error) {
	if reflect.ValueOf(val).Type() != m.v.Type().Elem() {
		err = fmt.Errorf("need %s not %T", m.v.Type().Elem(), val)
		return
	}
	m.v = reflect.Append(m.v, reflect.ValueOf(val))
	m.count++
	return
}

func (m *mySlice) Get(out interface{}) (err error) {
	if m.count == 0 {
		err = errors.New("no elem")
		return
	}
	if reflect.ValueOf(out).Kind() != reflect.Ptr ||
		reflect.ValueOf(out).Elem().Type() != m.v.Type().Elem() {
		err = fmt.Errorf("get: needs *%s but got %T", m.v.Type().Elem(), out)
		return
	}
	m.count--
	reflect.ValueOf(out).Elem().Set(m.v.Index(0))
	m.v = m.v.Slice(1, m.v.Len())
	return
}

//TODO：直接对slice复制会造成索引越界，但具体原因待查看源码
//初步查看因cap问题。
func (m *mySlice) RemoveElemFromSlice(elem interface{}) (err error) {
	if reflect.TypeOf(elem) != m.v.Type().Elem() {
		err = errors.New("invalid element")
		return
	}
	for i := 0; i < m.count; i++ {
		if m.v.Index(i).Interface() == elem {
			temp := reflect.AppendSlice(m.v.Slice(0, i), m.v.Slice(i+1, m.count))
			reflect.Copy(m.v, temp)
			m.count--
			m.v = m.v.Slice3(0, m.count, m.count)
		}
	}
	return
}

func (m *mySlice) List() interface{} {
	return m.v.Slice(0, m.count).Interface()
}

func (m *mySlice) Index(i int) (res interface{}, err error) {
	if i >= m.count {
		err = errors.New("index out of range")
		return
	}
	return m.v.Index(i).Interface(), nil
}
